/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sqlcommand;

import data.ManagerDatabase;
import data.Row;
import data.Table;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Quang
 */
public class Select extends Command {

    private List<String> tableName;
    private List<String> columns;
    private List<String> connective;
    private JConditions conditions;

    public Select(String strSQL, ManagerDatabase md) {
        super(strSQL, md);
        tableName = new ArrayList<>();
        manager = md;
//        for(int i=0; i<manager.getAllTables().size(); i++){
//            tableName.add(manager.getAllTables().get(i).getTableName());
//        }
        columns = new ArrayList<String>();
        connective = new ArrayList<String>();
        conditions = new MutileCondition();
        sql = Command.standardizeString(strSQL);

    }

//    public Select(ArrayList<String> cols, ArrayList<String> tablesname, ArrayList<String> connect) {
//        this.tableName = tablesname;
//        this.columns = cols;
//        conditions = new MutileCondition();
//        this.connective = connect;
//        
//    }
    /**
     * kiem tra xem chuoi nhap vao co phai la mot cau lenh select k?
     *
     * @param sql: chuoi can kiem tra
     * @return :null -> ko phai la cau lenh sql
     */
    public Command getCommand(MyError err) {

        // kiem tra xem co phai la cau lenh sql
        StringBuffer sbuff = new StringBuffer(getSql());
        int posSelect = Command.indexOfString(sbuff,"SELECT");
        int posFrom = Command.indexOfString(sbuff,"FROM");
        int posWhere = Command.indexOfString(sbuff,"WHERE");
        if (getListColumn(posSelect, posFrom, err, sbuff)) return null;

        if (getListTableName(posWhere, sbuff, posFrom, err)) return null;
        return getCondition(posWhere, sbuff, err);

    }

    private Command getCondition(int posWhere, StringBuffer sbuff, MyError err) {
        // lay danh sach cac dieu kien
        // khong co dk
        if (posWhere == -1) {
            conditions = null;
            return this;
        }     
        String s3 = sbuff.substring(posWhere + 6, sbuff.length());
        
        // kiem tra xem trong dieu kien co cau lenh select khac khong?
        int pos = s3.indexOf("SELECT");
        if(pos != -1 && s3.charAt(pos+6) == ' '){//co truy van long
//            Select select = new Select(s3, manager);
//            ArrayList<Row> rows = select.excute();
            if(tableName.size() >1){
                err.setError("Error! Truy van con chi ho tro 1 bang");
                return null;
            }
            setConditions(new SetCondition(s3,tableName.get(0),manager));
            
        }
        else{
            if (1 == getTableName().size()) {//co 1 bang            
                setConditions(new MutileCondition(s3, 1));
            } else if (2 == getTableName().size()) {//co 2 bang           
                setConditions(new MutileCondition(s3, 2));
            }
        }
        if(!getConditions().InitValue(err)){
            return null;
        }
        return this;
    }

    private boolean getListTableName(int posWhere, StringBuffer sbuff, int posFrom, MyError err) {
        // lay danh sach cac bang
        String s2;
        if (posWhere != -1) {
            s2 = sbuff.substring(posFrom + 5, posWhere - 1);
        } else {
            s2 = sbuff.substring(posFrom + 5, sbuff.length());
        }
        if (" ".equals(s2) || "M".equals(s2) || "W".equals(s2)) {
            return true;
        }
        StringBuilder tables = new StringBuilder(s2);
        int poscomm = tables.indexOf(",");
        if (poscomm == -1) {
            getTableName().add(s2);
        } else {
            String tb1 = tables.substring(0, poscomm);
            String tb2 = tables.substring(poscomm + 2, tables.length());
            getTableName().add(tb1);
            getTableName().add(tb2);
            tables.deleteCharAt(poscomm);
            if (tables.indexOf(",") != -1) {
                err.setError("Co nhieu hon 2 bang");
                return true;
            }
        }
        return false;
    }

    private boolean getListColumn(int posSelect, int posFrom, MyError err, StringBuffer sbuff) {
        if (posSelect != 0 || posFrom == -1) {
            err.setError("Error! khong co tu khoa SELECT, FROM");
            return true;
        }
        // lay danh sach cac cot
        String s1 = sbuff.substring(posSelect + 7, posFrom - 1);
        if (s1 == " " || s1 == "F" || s1 == "T") {
            return true;
        }
        StringBuffer cols = new StringBuffer(s1);
        if (cols.charAt(0) == '*') {
            getColumns().add("all");
        } else {
            while (cols.length() > 0) {
                int pos = cols.indexOf(",");
                // khong co dau ","
                if (pos == -1) {
                    getColumns().add(cols.toString());
                    break;
                }
                getColumns().add(cols.substring(0, pos));
                cols.delete(0, pos + 1);
            }
        }
        return false;
    }

    @Override
    public ArrayList<data.Row> excute(MyError err) {
        
        if (getCommand(err) == null) {            
            return null;
        }
        ArrayList<Row> rows = new ArrayList<>();
        Table tb = null;
        if (1 == this.tableName.size()) {//co 1 bang
            tb = manager.getTable(tableName.get(0));
        } else {//co 2 bang
            Table tb1 = manager.getTable(tableName.get(0));
            Table tb2 = manager.getTable(tableName.get(1));            
            tb = tb1.Descartes(tb2);
            
        }
        if(tb == null){
            err.setError("Error!! Khong tim thay bang!");
            return null;
        }
        int nRow = tb.getListRows().size();
        for (int i = 0; i < nRow; i++) {
            if (conditions == null) {
                return (ArrayList) tb.getListRows();
            }           
            else if (conditions.compare(tb.getListRows().get(i), err)) {
                rows.add(tb.getListRows().get(i));
            } else if (err.getError() != null) {
                System.out.println(err.getError());
                return null;
            }
        }
        return rows;



    }

    /**
     * @return the tableName
     */
    public List<String> getTableName() {
        return this.tableName;
    }

    /**
     * @param tableName the tableName to set
     */
    public void setTableName(List<String> tableName) {
        this.tableName = tableName;
    }

    /**
     * @return the columns
     */
    public List<String> getColumns() {
        return columns;
    }

    /**
     * @param columns the columns to set
     */
    public void setColumns(List<String> columns) {
        this.columns = columns;
    }

    /**
     * @return the connective
     */
    public List<String> getConnective() {
        return connective;
    }

    /**
     * @param connective the connective to set
     */
    public void setConnective(List<String> connective) {
        this.connective = connective;
    }

    /**
     * @return the conditions
     */
    public JConditions getConditions() {
        return conditions;
    }

    /**
     * @param conditions the conditions to set
     */
    public void setConditions(JConditions conditions) {
        this.conditions = conditions;
    }
}
